热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

放入|教室_onvif协议+高性能rtspclient打通大屏投屏协议

篇首语:本文由编程笔记#小编为大家整理,主要介绍了onvif协议+高性能rtspclient打通大屏投屏协议相关的知识,希望对你有一定的参考价值。1、onvif

篇首语:本文由编程笔记#小编为大家整理,主要介绍了onvif协议+高性能rtspclient打通大屏投屏协议相关的知识,希望对你有一定的参考价值。



1、onvif协议

  1.1 onvif简述和作用

a) 搜索列表
onvif协议本身是一个非常好的协议,帮助打通网内所有视频,搜索,播放和控制都是可以的。
b) 如何搜索
使用多播协议,以前写过很多多播的文章可以看,读者可以查看我其他文章,我是使用多播协议,因为正好,搜索所有大屏也需要使用多播协议,例如ssdp协议,而实际上onvif使用的是多播和soap,打通的流程过程就是同时搜索大屏和onvif,将两种设备放入到各自的列表,
c) 融合
这里又有另外一种模式了,就是我们的客户希望大屏作为一个融合过后的投屏,而不是一个一个地投上去,毕竟,投屏协议同时只支持一路视频,那么如何做呢,以下就是做法


  1.2 制作高性能rtspclient

为什么要rtspclient,因为onvif协议需要,抓住设备列表以后获取协议地址,然后开始做融合,问题是性能,rtsp拉流是比较耗性能和线程的,所以如果使用其他比如ffmpeg或者live555 等不符合要求。
任何高性能的客户端只能自己制作,使用单一进程联结多路,或者使用多进程联结多路,这个需要指挥调度,问题是我们需要视频融合做mcu,所以,使用单一进程是最好的,同时联结9路画到一个虚拟屏幕里,硬件解码,再重新硬件进行一路融合编码,发送到服务器,以下是rtspclient 伪代码

int options( sock and string)

cout << &#61;&#61;&#61;&#61;&#61;&#61;<<"OPTIONS"<<&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61; << endl;
char sendBuf[2048];
snprintf(sendBuf, 1024,
"OPTIONS rtsp://1.1.1.1:554/Streaming/Channels/101?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 2\\r\\n"
"User-Agent: qianbo/3.0.12 (18091589062)\\r\\n"
"\\r\\n");
//printf("sendBuf :\\n%s\\n", sendBuf);
sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));
return 0;

void describe(sock and string)

//发送describe返回401 安全需要认证机制
cout << &#61;&#61;&#61;&#61;&#61;&#61;<<"DESCRIBE"<<&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61; << endl;
char sendBuf[2048];
snprintf(sendBuf, 2048,
"DESCRIBE rtsp://1.1.1.1:554/Streaming/Channels/101?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 3\\r\\n"
"User-Agent: qianbo/1.1.1 (18091589062)\\r\\n"
"Accept: application/sdp\\r\\n"
"\\r\\n");
//printf("sendBuf :\\n%s\\n", sendBuf);
sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));
return 0;

int describe_authorization(sock and address, char *realm, char *nonce, const char *response)

//返回401时需要客户端认证
cout << "DESCRIBE_AUTHORIZATION" << endl;
char sendBuf[2048];
snprintf(sendBuf, 2048,
"DESCRIBE rtsp://1.1.1.1:554/Streaming/Channels/101?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 4\\r\\n"
"Authorization: Digest username&#61;\\"admin\\", realm&#61;\\"%s\\", nonce&#61;\\"%s\\", uri&#61;\\"rtsp://192.168.8.250:554/Streaming/Channels/101?transportmode&#61;unicast&profile&#61;Profile_1\\", response&#61;\\"%s\\"\\r\\n"
"User-Agent: qianbo/1.1.1 (18091589062)\\r\\n"
"Accept: application/sdp\\r\\n"
"\\r\\n",
realm, nonce, response);
return sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));


int setup(SOCKET& sock, sockaddr_in& sockAddr, char* realm, char* nonce, const char* response)

cout << "SETUP" << endl;
char sendBuf[2048];
snprintf(sendBuf, 2048,
"SETUP rtsp://192.168.8.250:554/Streaming/Channels/101/trackID&#61;1?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 5\\r\\n"
"Authorization: Digest username&#61;\\"admin\\", realm&#61;\\"%s\\", nonce&#61;\\"%s\\", uri&#61;\\"rtsp://192.168.8.250:554/Streaming/Channels/101/\\", response&#61;\\"%s\\"\\r\\n"
"User-Agent: qianbo/1.1.1 (18091589062)\\r\\n"
"Transport: RTP/AVP;unicast;client_port&#61;23332-23333\\r\\n"
"\\r\\n",
realm, nonce, response);
return sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));

int play(SOCKET& sock, sockaddr_in& sockAddr, char* realm, char* nonce, const char* response, char *session)

cout << "PLAY" << endl;
char sendBuf[2048];
snprintf(sendBuf, 2048,
"PLAY rtsp://192.168.8.250:554/Streaming/Channels/101?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 6\\r\\n"
"Authorization: Digest username&#61;\\"admin\\", realm&#61;\\"%s\\", nonce&#61;\\"%s\\", uri&#61;\\"rtsp://192.168.8.250:554/Streaming/Channels/101/\\", response&#61;\\"%s\\"\\r\\n"
"User-Agent: qianbo/1.1.1 (18091589062)\\r\\n"
"Session: %s\\r\\n"
"Range: npt&#61;0.000-\\r\\n"
"\\r\\n",
realm, nonce, response, session);
return sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));

int teardown(SOCKET& sock, sockaddr_in& sockAddr, char* realm, char* nonce, const char* response, char* session)

cout <<"TEARDOWN"" << endl;
char sendBuf[2048];
snprintf(sendBuf, 2048,
"TEARDOWN rtsp://192.168.8.250:554/Streaming/Channels/101/?transportmode&#61;unicast&profile&#61;Profile_1 RTSP/1.0\\r\\n"
"CSeq: 7\\r\\n"
"Authorization: Digest username&#61;\\"admin\\", realm&#61;\\"%s\\", nonce&#61;\\"%s\\", uri&#61;\\"rtsp://192.168.8.250:554/Streaming/Channels/101/\\", response&#61;\\"%s\\"\\r\\n"
"User-Agent: qianbo (18091589062)\\r\\n"
"Session: %s\\r\\n"
"\\r\\n",
realm, nonce, response, session);
return sendto(sock, sendBuf, strlen(sendBuf), 0, (sockaddr*)&sockAddr, sizeof(sockAddr));


1.3 onvif 探针

需要向网络中发送soap包探听

int sendProbe(int fd,const char *uuid,const char *types)

int r;
struct sockaddr_in srv;
memset( &srv, 0, sizeof(struct sockaddr_in) );
srv.sin_family &#61; AF_INET;
srv.sin_port &#61; htons(PUERTO);
srv.sin_addr.s_addr &#61; inet_addr(GRUPO);

char Probe[4096];
sprintf(Probe,""\\
""\\
""\\
"%s"\\
"urn:schemas-xmlsoap-org:ws:2005:04:discovery"\\
"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"\\
""\\
""\\
""\\
"%s"\\
""\\
""\\
""\\
"\\r\\n",uuid,types);
if( (r &#61; sendto(fd, Probe, strlen(Probe), 0, (struct sockaddr *)&srv, sizeof(srv))) < 0 )

cout<<"sendto failed"<<endl;
closesocket(fd);
return -1;

return 0;


2 投屏协议

读者可以参考我的其他投屏协议的文章&#xff0c;实际上投屏协议需要一个服务器&#xff0c;大部分大屏是支持各类协议&#xff0c;我们制作通用的rtsp服务器就行&#xff0c;使用tcp方式发送rtp&#xff0c;这样防止服务器在外网&#xff0c;而大屏在内网。
服务器在外网的时候有一个好处&#xff0c;就是可以将内网的视频传送到另外一个地方的大屏中&#xff0c;这是可以的。但是需要一个寻找大屏和通知大屏的内网代理&#xff0c;这个以后说。


3 发送和通知

需要使用ssdp等协议发送刚才融合的视频&#xff0c;把地址给到大屏&#xff0c;如果同时投屏到多个&#xff0c;那么多个大屏会同时播放融合的视频&#xff0c;这种方案还可以使用到教学种&#xff0c;可以将教学视频同时投放到多个教室。

后面的几节会具体讲述各个过程的具体实现&#xff0c;未完待续…


推荐阅读
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了VoLTE端到端业务详解|VoLTE用户注册流程相关的知识,希望对你有一定的参考价值。书籍来源:艾怀丽 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • PG12新增的VACUUM命令的SKIP_LOCKED选项
    PG12版本的VACUUM命令新增了SKIP_LOCKED选项,该选项使得vacuum命令在遇到被lock住的table时可以跳过并被视为成功执行。之前的版本中,vacuum命令会一直处于等待状态。本文还提到了PostgreSQL 12.1版本的相关信息。 ... [详细]
  • 本文介绍了如何使用MATLAB调用摄像头进行人脸检测和识别。首先需要安装扩展工具,并下载安装OS Generic Video Interface。然后使用MATLAB的机器视觉工具箱中的VJ算法进行人脸检测,可以直接调用CascadeObjectDetector函数进行检测。同时还介绍了如何调用摄像头进行人脸识别,并对每一帧图像进行识别。最后,给出了一些相关的参考资料和实例。 ... [详细]
  • 安装oracle软件1创建用户组、用户和目录bjdb节点下:[rootnode1]#groupadd-g200oinstall[rootnode1]#groupad ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了源码分析--ConcurrentHashMap与HashTable(JDK1.8)相关的知识,希望对你有一定的参考价值。  Concu ... [详细]
  • 指示|厂家_UDS协议
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了UDS协议相关的知识,希望对你有一定的参考价值。UDS的第二类诊断服务,数据传输 ... [详细]
  • AstridDAO 专访:波卡稳定币黑马 BAI
    加入Pol ... [详细]
  • struts2重点——ValueStack和OGNL
    一、值栈(ValueStack)1.实现类:OGNLValueStack2.对象栈:CompoundRoot( ... [详细]
  • 一面自我介绍对象相等的判断,equals方法实现。可以简单描述挫折,并说明自己如何克服,最终有哪些收获。职业规划表明自己决心,首先自己不准备继续求学了,必须招工作了。希望去哪 ... [详细]
  • Linux线程的同步和互斥
    目录1、线程的互斥2、可重入VS线程安全3、线程的同步1、线程的互斥 ... [详细]
author-avatar
wo1344165221
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有